package cn.iocoder.yudao.module.trade.order.dal.mysql;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.business.basic.dao.mapper.CoreMapper;
import cn.iocoder.yudao.framework.business.basic.dao.query.CoreLambdaQueryWrapper;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX;
import cn.iocoder.yudao.module.api.dine.enums.DineStatusEnum;
import cn.iocoder.yudao.module.api.trade.delivery.enums.DeliveryTypeEnum;
import cn.iocoder.yudao.module.api.trade.order.dto.TradeOrderQueryDTO;
import cn.iocoder.yudao.module.api.trade.order.enums.TradeOrderRefundStatusEnum;
import cn.iocoder.yudao.module.api.trade.order.enums.TradeOrderStatusCodeEnum;
import cn.iocoder.yudao.module.api.trade.order.enums.TradeOrderStatusEnum;
import cn.iocoder.yudao.module.api.trade.order.enums.TradeOrderTypeEnum;
import cn.iocoder.yudao.module.trade.order.dal.dataobject.TradeOrderDO;
import cn.iocoder.yudao.module.trade.order.vo.TradeOrderPageForVerifyReqVO;
import cn.iocoder.yudao.module.trade.order.vo.TradeOrderPageReqVO;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import jakarta.annotation.Nullable;
import org.apache.ibatis.annotations.Mapper;

import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;

import static cn.iocoder.yudao.module.api.supply.ConfigConstants.SUPPLY_NAME_ZXHX;

@Mapper
public interface TradeOrderMapper extends CoreMapper<TradeOrderDO> {

    default int updateByIdAndStatus(Long id, Integer status, TradeOrderDO update) {
        return update(update, new LambdaUpdateWrapper<TradeOrderDO>()
                .eq(TradeOrderDO::getId, id).eq(TradeOrderDO::getStatus, status));
    }

    default TradeOrderDO selectByNo(String no) {
        return selectOne(TradeOrderDO::getNo, no);
    }

    default TradeOrderDO selectByIdAndUserId(Long id, Long userId) {
        return selectOne(TradeOrderDO::getId, id, TradeOrderDO::getUserId, userId);
    }

    default PageResult<TradeOrderDO> selectPage(TradeOrderPageReqVO reqVO, Set<Long> userIds) {
        CoreLambdaQueryWrapper<TradeOrderDO> wrapper = new CoreLambdaQueryWrapper<>();
        wrapQueryCondition(wrapper, reqVO.getOrderStatus());
        wrapper.likeIfPresent(TradeOrderDO::getNo, reqVO.getNo())
                .eqIfPresent(TradeOrderDO::getUserId, reqVO.getUserId())
                .inIfPresent(TradeOrderDO::getUserId, userIds)
                .eqIfPresent(TradeOrderDO::getDeliveryType, reqVO.getDeliveryType())
                .eqIfPresent(TradeOrderDO::getType, reqVO.getType())
                .eqIfPresent(TradeOrderDO::getStatus, reqVO.getStatus())
                .eqIfPresent(TradeOrderDO::getPayChannelCode, reqVO.getPayChannelCode())
                .eqIfPresent(TradeOrderDO::getTerminal, reqVO.getTerminal())
                .eqIfPresent(TradeOrderDO::getLogisticsId, reqVO.getLogisticsId())
                .eqIfPresent(TradeOrderDO::getPickUpStoreId, reqVO.getPickUpStoreId())
                .inIfPresent(TradeOrderDO::getPickUpStoreId, reqVO.getPickUpStoreIds())
                .likeIfPresent(TradeOrderDO::getVerifyCode, reqVO.getVerifyCode())
                .betweenIfPresent(TradeOrderDO::getCreateTime, reqVO.getCreateTime())
                .orderByDesc(TradeOrderDO::getId);
        return selectPage(reqVO, wrapper);
    }

    default PageResult<TradeOrderDO> selectPageForVerify(TradeOrderPageForVerifyReqVO reqVO, Set<Long> userIds) {
        CoreLambdaQueryWrapper<TradeOrderDO> wrapper = new CoreLambdaQueryWrapper<>();
        wrapQueryCondition(wrapper, reqVO.getOrderStatus());
        wrapper.likeIfPresent(TradeOrderDO::getNo, reqVO.getNo())
                .eqIfPresent(TradeOrderDO::getUserId, reqVO.getUserId())
                .inIfPresent(TradeOrderDO::getUserId, userIds)
                .eqIfPresent(TradeOrderDO::getStatus, reqVO.getStatus())
                .betweenIfPresent(TradeOrderDO::getCreateTime, reqVO.getCreateTime())
                .isNotNull(TradeOrderDO::getVerifyCode)
                .orderByDesc(TradeOrderDO::getId);
        return selectPage(reqVO, wrapper);
    }


    // TODO @疯狂：如果用 map 返回，要不这里直接用 TradeOrderSummaryRespVO 返回？也算合理，就当  sql 查询出这么个玩意~~
    default List<Map<String, Object>> selectOrderSummaryGroupByRefundStatus(TradeOrderPageReqVO reqVO, Set<Long> userIds) {
        MPJLambdaWrapperX<TradeOrderDO> wrapper = new MPJLambdaWrapperX<>();
        wrapQueryCondition(wrapper, reqVO.getOrderStatus());
        return selectMaps(wrapper
                .selectAs(TradeOrderDO::getRefundStatus, "refundStatus")  // 售后状态
                .selectCount(TradeOrderDO::getId, "count") // 售后状态对应的数量
                .selectSum(TradeOrderDO::getPayPrice, "price")  // 售后状态对应的支付金额
                .likeIfPresent(TradeOrderDO::getNo, reqVO.getNo())
                .eqIfPresent(TradeOrderDO::getUserId, reqVO.getUserId())
                .eqIfPresent(TradeOrderDO::getDeliveryType, reqVO.getDeliveryType())
                .inIfPresent(TradeOrderDO::getUserId, userIds)
                .eqIfPresent(TradeOrderDO::getType, reqVO.getType())
                .eqIfPresent(TradeOrderDO::getStatus, reqVO.getStatus())
                .eqIfPresent(TradeOrderDO::getPayChannelCode, reqVO.getPayChannelCode())
                .eqIfPresent(TradeOrderDO::getTerminal, reqVO.getTerminal())
                .eqIfPresent(TradeOrderDO::getLogisticsId, reqVO.getLogisticsId())
                .inIfPresent(TradeOrderDO::getPickUpStoreId, reqVO.getPickUpStoreIds())
                .likeIfPresent(TradeOrderDO::getVerifyCode, reqVO.getVerifyCode())
                .betweenIfPresent(TradeOrderDO::getCreateTime, reqVO.getCreateTime())
                .groupBy(TradeOrderDO::getRefundStatus)); // 按售后状态分组
    }

    default PageResult<TradeOrderDO> selectPageByUserId(Long userId, PageParam pageParam, TradeOrderQueryDTO queryDTO) {
        CoreLambdaQueryWrapper<TradeOrderDO> wrapper = new CoreLambdaQueryWrapper<>();
        wrapper.eq(TradeOrderDO::getUserId, userId);
        if (queryDTO.getStatus() != null) {
            wrapper.eq(TradeOrderDO::getStatus, queryDTO.getStatus());
        } else {
            wrapQueryCondition(wrapper, queryDTO.getOrderStatus());
        }
        wrapper.in(CollUtil.isNotEmpty(queryDTO.getIds()), TradeOrderDO::getId, queryDTO.getIds());
        wrapper.eqIfPresent(TradeOrderDO::getType, queryDTO.getOrderType());
        wrapper.orderByDesc(TradeOrderDO::getId);
        return selectPage(pageParam, wrapper);
    }

    default PageResult<TradeOrderDO> selectPageByShopId(Long shopId, PageParam pageParam, TradeOrderQueryDTO queryDTO) {
        CoreLambdaQueryWrapper<TradeOrderDO> wrapper = new CoreLambdaQueryWrapper<>();
        wrapper.eq(TradeOrderDO::getShopId, shopId);
        wrapper.in(CollUtil.isNotEmpty(queryDTO.getIds()), TradeOrderDO::getId, queryDTO.getIds());
        if (queryDTO.getStatus() != null) {
            wrapper.eq(TradeOrderDO::getStatus, queryDTO.getStatus());
        } else {
            wrapQueryCondition(wrapper, queryDTO.getOrderStatus());
        }
        wrapper.eqIfPresent(TradeOrderDO::getType, queryDTO.getOrderType());
        wrapper.orderByDesc(TradeOrderDO::getId);
        return selectPage(pageParam, wrapper);
    }

    default PageResult<TradeOrderDO> selectPageByStaffId(Long shopId, Long staffId, PageParam pageParam, Integer dineStatus) {
        CoreLambdaQueryWrapper<TradeOrderDO> wrapper = buildStaffQueryWrapper(shopId, staffId, dineStatus);
        wrapper.orderByDesc(TradeOrderDO::getId);
        return selectPage(pageParam, wrapper);
    }

    private CoreLambdaQueryWrapper<TradeOrderDO> buildStaffQueryWrapper(Long shopId, Long staffId, Integer... dineStatus) {
        CoreLambdaQueryWrapper<TradeOrderDO> wrapper = new CoreLambdaQueryWrapper<>();
        wrapper.eq(TradeOrderDO::getShopId, shopId);
        wrapper.eq(TradeOrderDO::getType, TradeOrderTypeEnum.TAKE_AWAY.getType());
        if (dineStatus == null || dineStatus.length == 0) {
            // 已分派自己或待分派配送员的订单
            buildStaffQueryWrapper(staffId, wrapper);
            return wrapper;
        }
        if (dineStatus.length > 1) {
            // 配送员自己的指定状态的指定状态的订单
            wrapper.eq(TradeOrderDO::getRiderStaffId, staffId);
            wrapper.in(TradeOrderDO::getDineStatus, Arrays.stream(dineStatus).toList());
            return wrapper;
        }
        if (dineStatus[0] == null) {
            // 已分派自己或待分派配送员的订单
            buildStaffQueryWrapper(staffId, wrapper);
            return wrapper;
        }
        if (DineStatusEnum.ACCEPTED.getValue().equals(dineStatus[0])) {
            // 已分派自己或待分派配送员的订单
            wrapper.and(it ->
                    it.eq(TradeOrderDO::getRiderStaffId, staffId).or().isNull(TradeOrderDO::getRiderStaffId)
            );
            wrapper.in(TradeOrderDO::getDineStatus, DineStatusEnum.ACCEPTED.getValue(), DineStatusEnum.PACKED.getValue());
            return wrapper;
        }
        // 配送员自己的指定状态的订单
        wrapper.eq(TradeOrderDO::getRiderStaffId, staffId);
        wrapper.eqIfPresent(TradeOrderDO::getDineStatus, dineStatus[0]);
        return wrapper;
    }

    private void buildStaffQueryWrapper(Long staffId, CoreLambdaQueryWrapper<TradeOrderDO> wrapper) {
        // 待分派配送员或已分派自己的订单
        wrapper.and(it1 -> {
            it1.and(it2 -> {
                // status = 10 AND (rider_staff_id = 1945296995731517441 OR rider_staff_id IS NULL)
                it2.eq(TradeOrderDO::getStatus, TradeOrderStatusEnum.PAID.getStatus());
                it2.and(it3 -> {
                    // AND (rider_staff_id = 1945296995731517441 OR rider_staff_id IS NULL)
                    it3.eq(TradeOrderDO::getRiderStaffId, staffId);
                    it3.or();
                    it3.isNull(TradeOrderDO::getRiderStaffId);
                });
            });
            it1.or(it2 -> {
                // status = 20 AND rider_staff_id = 1945296995731517441
                it2.eq(TradeOrderDO::getStatus, TradeOrderStatusEnum.DOING.getStatus());
                it2.eq(TradeOrderDO::getRiderStaffId, staffId);
            });
        });
    }

    @SuppressWarnings("DuplicatedCode")
    static void wrapQueryCondition(LambdaQueryWrapper<TradeOrderDO> wrapper, String orderStatus) {
        if (StrUtil.isBlank(orderStatus)) {
            return;
        }
        TradeOrderStatusCodeEnum status = TradeOrderStatusCodeEnum.codeOf(orderStatus.toLowerCase());
        switch (status) {
            case PAYMENT:
                wrapper.eq(TradeOrderDO::getStatus, TradeOrderStatusEnum.UNPAID.getStatus());
                break;
            case PAID:
                wrapper.eq(TradeOrderDO::getStatus, TradeOrderStatusEnum.PAID.getStatus());
                break;
            case RIDER:
                wrapper.eq(TradeOrderDO::getStatus, TradeOrderStatusEnum.PAID.getStatus());
                wrapper.in(TradeOrderDO::getDeliveryType, DeliveryTypeEnum.EXPRESS.getType(), DeliveryTypeEnum.TAKE_OUT.getType());
                break;
            case DOING:
                wrapper.in(TradeOrderDO::getStatus, TradeOrderStatusEnum.PAID.getStatus(), TradeOrderStatusEnum.DOING.getStatus());
                break;
            case RECEIVE:
                wrapper.eq(TradeOrderDO::getStatus, TradeOrderStatusEnum.DOING.getStatus());
                wrapper.in(TradeOrderDO::getDeliveryType, DeliveryTypeEnum.EXPRESS.getType(), DeliveryTypeEnum.TAKE_OUT.getType());
                break;
            case CLERK:
                wrapper.in(TradeOrderDO::getStatus, TradeOrderStatusEnum.PAID.getStatus(), TradeOrderStatusEnum.DOING.getStatus());
                wrapper.in(TradeOrderDO::getDeliveryType, DeliveryTypeEnum.PICK_UP.getType(), DeliveryTypeEnum.VERIFY.getType(), DeliveryTypeEnum.ONSITE.getType());
                break;
            case COMPLETE:
                wrapper.eq(TradeOrderDO::getStatus, TradeOrderStatusEnum.COMPLETED.getStatus());
                break;
            case COMMENT:
                wrapper.eq(TradeOrderDO::getStatus, TradeOrderStatusEnum.COMPLETED.getStatus());
                wrapper.eq(TradeOrderDO::getCommentStatus, false);
                break;
            case CLOSED:
                wrapper.eq(TradeOrderDO::getStatus, TradeOrderStatusEnum.CLOSED.getStatus());
                break;
            case REFUND:
                wrapper.ne(TradeOrderDO::getRefundStatus, TradeOrderRefundStatusEnum.NONE.getStatus());
                break;
            case ALL:
            default:
                break;
        }
    }

    @SuppressWarnings("DuplicatedCode")
    static void wrapQueryCondition(MPJLambdaWrapper<TradeOrderDO> wrapper, String orderStatus) {
        if (StrUtil.isBlank(orderStatus)) {
            return;
        }
        TradeOrderStatusCodeEnum status = TradeOrderStatusCodeEnum.codeOf(orderStatus.toLowerCase());
        switch (status) {
            case PAYMENT:
                wrapper.eq(TradeOrderDO::getStatus, TradeOrderStatusEnum.UNPAID.getStatus());
                break;
            case PAID:
                wrapper.eq(TradeOrderDO::getStatus, TradeOrderStatusEnum.PAID.getStatus());
                break;
            case RIDER:
                wrapper.eq(TradeOrderDO::getStatus, TradeOrderStatusEnum.PAID.getStatus());
                wrapper.in(TradeOrderDO::getDeliveryType, DeliveryTypeEnum.EXPRESS.getType(), DeliveryTypeEnum.TAKE_OUT.getType());
                break;
            case DOING:
                wrapper.eq(TradeOrderDO::getStatus, TradeOrderStatusEnum.DOING.getStatus());
                break;
            case RECEIVE:
                wrapper.eq(TradeOrderDO::getStatus, TradeOrderStatusEnum.DOING.getStatus());
                wrapper.in(TradeOrderDO::getDeliveryType, DeliveryTypeEnum.EXPRESS.getType(), DeliveryTypeEnum.TAKE_OUT.getType());
                break;
            case CLERK:
                wrapper.in(TradeOrderDO::getStatus, TradeOrderStatusEnum.PAID.getStatus(), TradeOrderStatusEnum.DOING.getStatus());
                wrapper.in(TradeOrderDO::getDeliveryType, DeliveryTypeEnum.PICK_UP.getType(), DeliveryTypeEnum.VERIFY.getType());
                break;
            case COMPLETE:
                wrapper.eq(TradeOrderDO::getStatus, TradeOrderStatusEnum.COMPLETED.getStatus());
                break;
            case COMMENT:
                wrapper.eq(TradeOrderDO::getStatus, TradeOrderStatusEnum.COMPLETED.getStatus());
                wrapper.eq(TradeOrderDO::getCommentStatus, false);
                break;
            case CLOSED:
                wrapper.eq(TradeOrderDO::getStatus, TradeOrderStatusEnum.CLOSED.getStatus());
                break;
            case REFUND:
                wrapper.ne(TradeOrderDO::getRefundStatus, TradeOrderRefundStatusEnum.NONE.getStatus());
                break;
            case ALL:
            default:
                break;
        }
    }

    default Long selectCountByShopIdAndStatus(Long shopId, @Nullable Integer status, @Nullable Boolean commentStatus) {
        return selectCount(new CoreLambdaQueryWrapper<TradeOrderDO>()
                .eq(TradeOrderDO::getShopId, shopId)
                .eqIfPresent(TradeOrderDO::getStatus, status)
                .eqIfPresent(TradeOrderDO::getCommentStatus, commentStatus));
    }

    default Long selectCountByUserIdAndStatus(Long userId, @Nullable List<Integer> deliveryTypes, @Nullable Integer status, @Nullable Boolean commentStatus) {
        return selectCount(new CoreLambdaQueryWrapper<TradeOrderDO>()
                .eq(TradeOrderDO::getUserId, userId)
                .inIfPresent(TradeOrderDO::getDeliveryType, deliveryTypes)
                .eqIfPresent(TradeOrderDO::getStatus, status)
                .eqIfPresent(TradeOrderDO::getCommentStatus, commentStatus));
    }

    default Long selectCountByStaffIdAndStatus(Long shopId, Long staffId, @Nullable Integer... dineStatus) {
        return selectCount(buildStaffQueryWrapper(shopId, staffId, dineStatus));
    }

    default TradeOrderDO selectOrderByIdAndUserId(Long orderId, Long loginUserId) {
        CoreLambdaQueryWrapper<TradeOrderDO> wrapper = new CoreLambdaQueryWrapper<>();
        wrapper.eq(TradeOrderDO::getId, orderId);
        wrapper.eq(TradeOrderDO::getUserId, loginUserId);
        wrapper.limitN(1);
        return selectOne(wrapper);
    }

    default List<TradeOrderDO> selectListByStatusAndCreateTimeLt(Integer status, LocalDateTime createTime) {
        return selectList(new LambdaUpdateWrapper<TradeOrderDO>()
                .eq(TradeOrderDO::getStatus, status)
                .lt(TradeOrderDO::getCreateTime, createTime));
    }

    default List<TradeOrderDO> selectListByStatusAndDeliveryTimeLt(Integer status, LocalDateTime deliveryTime) {
        return selectList(new LambdaUpdateWrapper<TradeOrderDO>()
                .eq(TradeOrderDO::getStatus, status)
                .lt(TradeOrderDO::getDeliveryTime, deliveryTime));
    }

    default List<TradeOrderDO> selectListByStatusAndReceiveTimeLt(Integer status, LocalDateTime receive,
                                                                  Boolean commentStatus) {
        return selectList(new LambdaUpdateWrapper<TradeOrderDO>()
                .eq(TradeOrderDO::getStatus, status)
                .lt(TradeOrderDO::getReceiveTime, receive)
                .eq(TradeOrderDO::getCommentStatus, commentStatus));
    }

    default List<TradeOrderDO> selectListByUserIdAndActivityId(Long userId, Long activityId, TradeOrderTypeEnum type) {
        CoreLambdaQueryWrapper<TradeOrderDO> queryWrapperX = new CoreLambdaQueryWrapper<>();
        queryWrapperX.eq(TradeOrderDO::getUserId, userId);
        if (TradeOrderTypeEnum.isSeckill(type.getType())) {
            queryWrapperX.eq(TradeOrderDO::getSeckillActivityId, activityId);
        }
        if (TradeOrderTypeEnum.isBargain(type.getType())) {
            queryWrapperX.eq(TradeOrderDO::getBargainActivityId, activityId);
        }
        if (TradeOrderTypeEnum.isCombination(type.getType())) {
            queryWrapperX.eq(TradeOrderDO::getCombinationActivityId, activityId);
        }
        if (TradeOrderTypeEnum.isPoint(type.getType())) {
            queryWrapperX.eq(TradeOrderDO::getPointActivityId, activityId);
        }
        return selectList(queryWrapperX);
    }

    default TradeOrderDO selectOneByVerifyCode(String verifyCode) {
        return selectOne(TradeOrderDO::getVerifyCode, verifyCode);
    }

    default TradeOrderDO selectByUserIdAndCombinationActivityIdAndStatus(Long userId, Long combinationActivityId, Integer status) {
        CoreLambdaQueryWrapper<TradeOrderDO> wrapper = new CoreLambdaQueryWrapper<>();
        wrapper.eq(TradeOrderDO::getUserId, userId);
        wrapper.eq(TradeOrderDO::getStatus, status);
        wrapper.eq(TradeOrderDO::getCombinationActivityId, combinationActivityId);
        wrapper.limitN(1);
        return selectOne(wrapper);
    }

    default TradeOrderDO searchBySupplyRelatedNo(String orderSn) {
        CoreLambdaQueryWrapper<TradeOrderDO> wrapper = new CoreLambdaQueryWrapper<>();
        wrapper.apply("FIND_IN_SET({0}, supply_related_nos) > 0", orderSn);
        wrapper.limitN(1);
        return selectOne(wrapper);
    }

    default List<TradeOrderDO> selectWillSubmitSupplyOrders() {
        CoreLambdaQueryWrapper<TradeOrderDO> wrapper = new CoreLambdaQueryWrapper<>();
        wrapper.eq(TradeOrderDO::getPayStatus, true);
        wrapper.eq(TradeOrderDO::getSupplyName, SUPPLY_NAME_ZXHX);
        wrapper.isNull(TradeOrderDO::getSupplyRelatedOrders);
        return selectList(wrapper);
    }

    default int selectCountByShopIdAndUserId(Long shopId, Long userId) {
        Long count = selectCount(new CoreLambdaQueryWrapper<TradeOrderDO>()
                .eq(TradeOrderDO::getShopId, shopId)
                .eq(TradeOrderDO::getUserId, userId)
                .eq(TradeOrderDO::getPayStatus, true));
        if (count == null) {
            return 0;
        }
        return count.intValue();
    }

    default int selectTodayOrderCount(Long shopId, Integer type) {
        Long count = selectCount(new CoreLambdaQueryWrapper<TradeOrderDO>()
                .eq(TradeOrderDO::getShopId, shopId)
                .eq(TradeOrderDO::getType, type)
                .in(TradeOrderDO::getStatus, List.of(TradeOrderStatusEnum.PAID.getStatus(), TradeOrderStatusEnum.DOING.getStatus(), TradeOrderStatusEnum.COMPLETED.getStatus()))
                .ge(TradeOrderDO::getCreateTime, LocalDateTime.now().withHour(0).withMinute(0).withSecond(0)));
        if (count == null) {
            return 0;
        }
        return count.intValue();
    }

    default List<TradeOrderDO> selectAcceptableList() {
        CoreLambdaQueryWrapper<TradeOrderDO> wrapper = new CoreLambdaQueryWrapper<>();
        wrapper.eq(TradeOrderDO::getType, TradeOrderTypeEnum.TAKE_AWAY.getType());
        wrapper.eq(TradeOrderDO::getStatus, TradeOrderStatusEnum.PAID.getStatus());
        wrapper.eq(TradeOrderDO::getDineStatus, DineStatusEnum.PENDING.getValue());
        return selectList(wrapper);
    }

    default List<TradeOrderDO> selectAssignableList() {
        CoreLambdaQueryWrapper<TradeOrderDO> wrapper = new CoreLambdaQueryWrapper<>();
        wrapper.eq(TradeOrderDO::getType, TradeOrderTypeEnum.TAKE_AWAY.getType());
        wrapper.in(TradeOrderDO::getDineStatus, DineStatusEnum.ACCEPTED.getValue(), DineStatusEnum.PACKED.getValue());
        wrapper.and(it -> {
            it.isNull(TradeOrderDO::getRiderStaffId);
            it.or();
            it.eq(TradeOrderDO::getRiderStaffId, 0);
        });
        return selectList(wrapper);
    }

    default List<TradeOrderDO> selectAssignedButNotArrivalOrders(Long shopId, int minute) {
        CoreLambdaQueryWrapper<TradeOrderDO> wrapper = new CoreLambdaQueryWrapper<>();
        wrapper.eq(TradeOrderDO::getType, TradeOrderTypeEnum.TAKE_AWAY.getType());
        wrapper.eq(TradeOrderDO::getShopId, shopId);
        // 已派单
        wrapper.gt(TradeOrderDO::getRiderStaffId, 0);
        // 还未开始配送
        wrapper.in(TradeOrderDO::getDineStatus, DineStatusEnum.ASSIGNED.getValue(), DineStatusEnum.PACKED.getValue());
        // 派单时间在5分钟内
        wrapper.ge(TradeOrderDO::getAssignedTime, LocalDateTime.now().minusMinutes(minute));
        List<TradeOrderDO> list = selectList(wrapper);
        if (CollUtil.isEmpty(list)) {
            return null;
        }
        return list;
    }

}
